webpack一堆筆記
2021-11-15 Mon
指令輸入npm install webpack webpack-cli --save-dev 開始安裝
webpack 優點
- 編譯多種東西像是 scss react pug 還可以壓縮圖片、html
- 多人團隊開發 統一開發
- 可以記錄套件的版本號
- 打包成一隻 JS 檔案解決 src 非同步的問題
- 跨瀏覽器版本的問題
- 例如 babel、polyfill 等等
使用 plugin 需要注意的地方
使用 plugin 的時候必須 reuire 後方可在配置檔使用例如以下程式碼
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");如何建置一個簡單有 webpack 伺服器和 html 模板自動注入 JS 的設定檔
在 npm 套件的部分安裝 corss-env、webpack-dev-server、html-webpack-plugin
使用 cross-env 使得在 windows 或 linux 的指令統一
由於在 linux 系統底下和 windows 系統設置環境變數的指令不同,為了統一執行指令因此使用npm install corss-env --save-dev指令
如果是在 linux 指令設置環境變數的話是輸入 export 如下
"script":{
"build" : "export NODE_ENV=development webpack"
}如果是在 winodws 指令設置環境變數的話是輸入 set 如下
"script":{
"build" : "set NODE_ENV=development webpack"
}為了統一設定因此使用 corss-env,指令如下
"start": "cross-env NODE_ENV=development webpack",這裡設置幾個 package.json 腳本 在 script 裡面添加自己的腳本,script 裡面的 key 可以自己取 可以參照以下的名字取名
"scripts": {
"start": "cross-env NODE_ENV=development webpack",
"deploy": "cross-env NODE_ENV=production webpack"
},在 webpack.config.js 設定檔的部分使用
const path = require('path');
const modeEnv = process.env.NODE_ENV === 'production' ? 'production' : 'development' //使用node的process.env抓取環境變數來判斷當下的
module.exports = {
mode: modeEnv,//設定要打包的模式可以設定production或development
entry: './src/js/index.js',
output: {
path: path.resolve(__dirname, 'dist'),//使用絕對路徑方式設定打包後產生出的資料夾
filename: 'bundle.js',//打包後要取的名字
},
}
順帶一提如果 entry 進入點有多個的話可以使用物件的方式 通常原本 src 內的注入檔案名稱叫做什麼的話,在 entry 的物件 key 值也會設定相同的名稱
範例如下
module.exports = {
entry: {
home: './home.js',
about: './about.js',
contact: './contact.js',
},
};使用 webpack 的伺服器
為了測試方便使用 webpack 的伺服器來開啟網頁進行測試
指令輸入npm install webpack-dev-server --save-dev安裝
在 webpack.config 添加如下
devServer:{
static :{
directory: path.join(__dirname, './dist/')
},
open: true, //自動打開瀏覽器
port: 8080,//開啟的port號是8080
hot:true,//4.0.0默認是開啟的
}cross-env
設定環境變數為 NODE_ENV=production
npm install cross-env --save-dev
html 模板而且也可以自動注入 script
npm install html-webpack-plugin --save-dev
在 webpack.config.js 的底下帶入參數 例如 title 參數,範例如下
plugins: [new HtmlWebpackPlugin({
title: 'Custom template',
filename: 'index.html',//這樣會在output指定的資料夾建立一個html資料夾後再產出名叫index.html的檔案
template:'src/html/index.html',//模板的來源
chunks: ['index','index2'] //指定注入哪些js文件,如果沒有設定預設是全部注入
})],建立一個 html 模板的資料夾 其中部分可以帶入模板語言如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title><!-- 使用<% %>來添加參數這裡是取得key是title的參數 -->
</head>
<body>
hello world!
</body>
</html>如何編譯 sass 並且產生有 hash 值的獨立 css 檔案
npm install sass-loader node-sass --save-dev
這邊 npm 安裝了兩個套件 一個是 sass 用來編譯 sass 一個是 sass-loader 用來讓 webpack 讀取 sass 檔案
另外由於編譯完的 css 檔案還是要給 webpack 讀取因此得安裝css-loader
安裝npm install css-loader -D
最後如果希望將 css 注入到 html 在上方用<style></style>樣式的話就使用 style-loader
在 webpack.config.js 裡面的 module 的 rules 配置如下
module.exports = {
mode: modeEnv,
module: {
rules: [
{
test: /\.s[ac]ss$/i,//使用正則表達式選擇副檔名含有scss或sass的檔案
// 使用loader webpack是從後面讀到前面所以sass-loader放陣列最後一筆不過是優先處理的loader
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
entry: './src/js/index.js',
//以下省略另外記得在 index.js 入口點的 js 檔案要 import scss 語法如下
import '../scss/all.scss'
console.log("hello");如果希望建置獨立的 css 檔案的話就用 MiniCssExtractPlugin
使用npm i mini-css-extract-plugin -D
在 webpack.config 設置檔案需要改成使用MiniCssExtractPlugin.loader和 plugin 要添加 MiniCssExtractPlugin 程式碼如下
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const modeEnv = process.env.NODE_ENV === 'production' ? 'production' : 'development'
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: modeEnv,
module: {
rules: [
{
test: /\.s[ac]ss$/i,
// 把 sass-loader 放在首要處理 (第一步)
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
entry: //中間省略
//中間省略//中間省略//中間省略//中間省略//中間省略
//中間省略//中間省略//中間省略//中間省略//中間省略
//中間省略//中間省略//中間省略//中間省略//中間省略
plugins: [
new HtmlWebpackPlugin({
title: 'Custom template',
filename: 'html/index.html',
template:'src/html/index.html'
}),
new MiniCssExtractPlugin({
filename: "./css/[contenthash].bundle.css"
//filename的value地方意思是產生出css資料夾並且隨機產生hash檔名+bundle的css,產生隨機檔名可以避免瀏覽器快取
}),
],
}postcss 編譯 css 讓之前瀏覽器支援且自動加入語法前綴
如果想要將新版的 css 轉成舊版的 css 就需要 postcss-preset-env 套件
使用npm i postcss-preset-env -D
如果想要讓 css 自動加入前綴的話就要安裝 autoprefixer 套件
使用npm i autoprefixer -D
不過在使用 postcss-preset-env 或者 autoprefixer 的套件的時候必須預先安裝 這時候在 webpack.config.js 的配置就要改成如下
module.exports = {
mode: modeEnv,
module: {
rules: [
{
test: /\.s[ac]ss$/i,
// 把 sass-loader 放在首要處理 (第一步)
use: [MiniCssExtractPlugin.loader, 'css-loader','postcss-loader', 'sass-loader'],
},
],
},
//以下省略
//以下省略
//以下省略
}接下來建議新增一個 postcss.config.js 檔案 postcss-loader 會自動搜尋如果檔名叫做 postcss.config.js 的檔案就會讀取 裡面我們配置如下
module.exports = {
map: true,//是否開啟source-map
plugins: [require('postcss-preset- env'),require('autoprefixer'),]
//引入postcss-preset-env和autoprefixer
};另外瀏覽器設定也建議抽離出來成一個檔案,因此官方說新增一個.browserslistrc 設置如下
last 1 version
> 1%
IE 10 # sorry詳情可以搜尋 Browserslist 的文件 BrowserslistGitHub
如果 css 裡面有要載入圖片的話,可以對圖片處理的相關設定
在 webpack4 以前需要 file-loader 或者 url-loader webpack5 只需要在webpack.config添加就好了 程式碼如下
module.exports = {
mode: modeEnv,
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader','postcss-loader', 'sass-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[hash][name][ext]' //建立至images資料夾且自動產生hash和原檔案名稱和副檔名
},
},
//主要是這邊 添加此項配置來讓webpack對以上副檔名做處理
],
},想要使用 base64 解決圖片檔案多次對伺服器發送請求
如果想要設置多少 kb 以下壓縮成 base64 的話可以參照以下配置 如果未設定的話,預設是 8kb 以下就會自動轉成 base64 而不會另外生成 jpg 檔案
使用 base64 可以避免小圖片和伺服器多次請求,因為是夾帶在 css 檔案裡面
module.exports = {
mode: modeEnv,
module: {
rules: [
{
test: /\.s[ac]ss$/i,
// 把 sass-loader 放在首要處理 (第一步)
use: [MiniCssExtractPlugin.loader, 'css-loader','postcss-loader', 'sass-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'images/[hash][name][ext]'
},
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 //在多少位元組以下就變成base64
}
}
},
],
},
//以下省略
//以下省略
//以下省略
}為了向下相容瀏覽器使用 babel 幫我們轉換成以前的 JS 語法
首先要安裝babel-loader 和 @babel/core
npm install --save-dev babel-loader @babel/core
在 webpack.config 裡面的 module 添加規則
如下
module.exports = {
mode: modeEnv,
module: {
rules: [ {
test: /\.m?js$/,
exclude: /node_modules/, //node module底下的東西就不用做了
use: {
loader: "babel-loader",
}
}]
}
}上面設定了 exclude 就表示在 node_modules 資料夾底下的不用透過 bable 轉換
如果你想要支援 2015 到現在的語法就要安裝 preset-env
npm install @babel/preset-env --save-dev
新建一個 babel.config.json 內容如下
{
"presets": ["@babel/preset-env"],
}之後去抓你的.browserslistrc 的檔案看你需要支援到哪個版本的瀏覽器
你也可以自行設定內容在 babel.config.json 這個檔案
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
}
}
]
]
}如果使用 async await 的話
如果要使用 async await 的話在 bable 要安裝如下
npm i @babel/runtime regenerator-runtime
然後在 babel.config 添加以下片段
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/transform-runtime"]
]
}最後你在 js 檔案就可以使用async await了 範例代碼如下
(async function (){
const a= await fetch('某個API');
const b = await a.json();
console.log(b);
}())Babel ReferenceError: regeneratorRuntime is not defined How to fix regeneratorRuntime is not defined?
想要即時更新的話使用 watch 指令
在 package.json 添加 script 指令如下
"scripts": {
"watch": "cross-env NODE_ENV=development webpack --watch",//添加這一行
"start": "cross-env NODE_ENV=development webpack",
"server": "cross-env NODE_ENV=development webpack server",
"deploy": "cross-env NODE_ENV=production webpack",
"deploy-server": "cross-env NODE_ENV=production webpack server"
},每次自動先清除 dist 資料夾的東西可以在 output 設定
module.exports = {
mode: modeEnv,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
clean: true //設定這樣就可以自動清除之後再
},
}